package com.lysj.admin.master.auth.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.lysj.admin.master.CacheManager;
import com.lysj.admin.master.auth.domain.Permission;
import com.lysj.admin.master.auth.domain.RolePermission;
import com.lysj.admin.master.auth.domain.User;
import com.lysj.admin.master.auth.mapper.PermissionMapper;
import com.lysj.admin.master.auth.mapper.RolePermissionMapper;
import com.lysj.admin.master.auth.mapper.UserMapper;
import com.lysj.admin.master.auth.vo.PermissionVO;
import com.lysj.admin.master.common.cache.RedisKeyEnum;
import com.lysj.admin.master.common.cache.RedisUtil;
import com.lysj.admin.master.common.exception.BaseException;
import com.lysj.admin.master.common.spring.base.BaseRepository;
import com.lysj.admin.master.common.spring.base.BaseService;
import com.lysj.admin.master.common.spring.mpbase.IdEntity;
import com.lysj.admin.master.common.spring.mpbase.MyService;
import com.lysj.admin.master.common.validation.Validation;
import com.lysj.admin.master.common.validation.domain.BindingResult;
import com.lysj.admin.master.common.web.ParamUtil;
import com.lysj.admin.master.common.web.Resp;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.transaction.Transactional;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Created by zk on 2019-12-05 2:23
 * @description
 */
@Slf4j
@Service
@Transactional
public class PermissionService extends MyService<PermissionMapper, Permission> {
    //    @Resource
//    private PermissionMapper permissionMapper;
//    @Resource
//    private RolePermissionMapper rolePermissionMapper;
//    @Resource
//    private UserMapper userMapper;
    @Resource
    private RolePermissionService rolePermissionService;
    @Resource
    private PermissionService permissionService;
    @Resource
    private UserService userService;
    @Resource
    private AdminAuthentication adminAuthentication;
    @Resource
    private CacheManager cacheManager;
    @Resource
    private RedisUtil redisUtil;

    @Transactional
    public void deletePermission(String[] ids) {
        if (ids != null && ids.length > 0) {
            List<String> idList = Arrays.asList(ids);
            int count = this.lambdaQuery()
                    .select(Permission::getLevel)
                    .in(IdEntity::getId, idList)
                    .eq(Permission::getLevel, 3)
                    .count();
//            rolePermissionMapper.deleteByPermissionIdIn(Arrays.asList(ids));
            LambdaQueryWrapper<RolePermission> wrapper = new LambdaQueryWrapper<>();
            wrapper.in(RolePermission::getPermissionId, idList);
            rolePermissionService.remove(wrapper);
            permissionService.removeByIds(idList);
            if (count > 0) {
                cacheManager.initAdminPermissionRoleCache();
            }
            redisUtil.delete(RedisKeyEnum.ROLE_PERMISSION);
        }
    }

    @Transactional
    public void updatePermission(Permission entity) {
        if (ParamUtil.isBlank(entity.getId())) {
            throw new BaseException(Resp.ResStatus.PARAM_ERROR, "id不能为空");
        }
        Permission e = this.getById(entity.getId());
        if (e == null) {
            throw new BaseException(Resp.ResStatus.PARAM_ERROR, "该权限不存在");
        }
        boolean pathUpdate = false;
        if (!e.getPath().equals(entity.getPath())) {
            pathUpdate = true;
        }
        //获取Hutool拷贝实例
        CopyOptions copyOptions = CopyOptions.create();
        //忽略为null值得属性
        copyOptions.setIgnoreNullValue(true);
        //进行属性拷贝
        BeanUtil.copyProperties(entity, e, copyOptions);
        //对实体类中的@validation注解进行校验
        BindingResult bindingResult = Validation.valid(e);
        if (!bindingResult.isFlag()) {
            throw new BaseException(Resp.ResStatus.PARAM_ERROR, bindingResult.getMessage().get(0));
        }
        updateById(e);
        redisUtil.delete(RedisKeyEnum.ROLE_PERMISSION);
        if (pathUpdate) {
            cacheManager.initAdminPermissionRoleCache();
        }
    }

    public List<PermissionVO> findMenuList(String roleId) {
//        User user = redisUtil.get(RedisKeyEnum.USER, userId, () -> userService.getById(userId));
//        User user = userService.getById(userId);
//        List<RolePermission> rolePermissions = rolePermissionMapper.findByRoleId(user.getRoleId());
        List<RolePermission> rolePermissions = rolePermissionService.lambdaQuery()
                .select(RolePermission::getPermissionId)
                .eq(RolePermission::getRoleId, roleId)
                .list();
        //获取这些角色的所有权限
        Set<String> permissionIds = rolePermissions.parallelStream()
                .map(RolePermission::getPermissionId)
                .collect(Collectors.toSet());
        if (ParamUtil.isBlank(permissionIds)) {
            return new ArrayList<>();
        }
//        List<Permission> permissions = permissionMapper.findByLevelNotAndIdIn(3, permissionIds);
        List<Permission> permissions = permissionService.lambdaQuery()
                .in(!ParamUtil.isBlank(permissionIds), IdEntity::getId, permissionIds)
                .ne(Permission::getLevel, 3)
                .list();
        Map<String, List<Permission>> levelTwo = permissions.parallelStream()
                .filter(permission -> permission.getLevel() == 2)
                .sorted(Comparator.comparing(Permission::getSortOrder))
                .collect(Collectors.groupingBy(Permission::getParentId, LinkedHashMap::new, Collectors.toList()));
        Map<String, Permission> levelOne = permissions.parallelStream()
                .filter(permission -> permission.getLevel() == 1)
                .sorted(Comparator.comparing(Permission::getSortOrder))
                .collect(Collectors.toMap(Permission::getId, p -> p, (p1, p2) -> p2, LinkedHashMap::new));
        List<PermissionVO> permissionVOList = new ArrayList<>(levelOne.size());
        levelOne.forEach((id, p) -> {
            PermissionVO permissionVO = new PermissionVO();
            BeanUtil.copyProperties(p, permissionVO);
            List<Permission> children = levelTwo.get(id);
            List<PermissionVO> childrenVOList = new ArrayList<>();
            if (children != null) {
                for (Permission child : children) {
                    PermissionVO vo = new PermissionVO();
                    BeanUtil.copyProperties(child, vo);
                    childrenVOList.add(vo);
                }
            }
            permissionVO.setChildrenVO(childrenVOList);
            permissionVOList.add(permissionVO);
        });
        return permissionVOList;
    }

    public List<Permission> findAllList(String iss) {
//        List<Permission> permissions = permissionMapper.findByLevelOrderBySortOrder(1);
        List<Permission> permissions = permissionService.lambdaQuery()
                .eq(Permission::getLevel, 1)
                .eq(Permission::getType, iss)
                .orderByAsc(Permission::getSortOrder)
                .list();
        for (Permission p1 : permissions) {
//            List<Permission> children1 = permissionMapper.findByParentIdOrderBySortOrder(p1.getId());
            List<Permission> children1 = permissionService.lambdaQuery()
                    .eq(Permission::getParentId, p1.getId())
                    .orderByAsc(Permission::getSortOrder)
                    .list();
            p1.setChildren(children1);
            for (Permission p2 : children1) {
                List<Permission> children2 = permissionService.lambdaQuery()
                        .eq(Permission::getParentId, p2.getId())
                        .orderByAsc(Permission::getSortOrder)
                        .list();
                p2.setChildren(children2);
            }
        }
        return permissions;
    }
}
